package com.example.sokecttest.config;

import com.example.sokecttest.entity.ConsultationSession;
import com.example.sokecttest.entity.WebSocketMessage;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint("/websocket/{role}/{userId}")
@Component
public class MedicalWebSocketHandler {
    // 注入配置好的ObjectMapper（关键）
    private static ObjectMapper objectMapper;

    @Autowired
    public void setObjectMapper(ObjectMapper mapper) {
        MedicalWebSocketHandler.objectMapper = mapper;
    }
    // 存储所有在线医生 (doctorId -> Session)
    private static final Map<String, Session> doctorSessions = new ConcurrentHashMap<>();
    // 存储所有在线用户 (userId -> Session)
    private static final Map<String, Session> userSessions = new ConcurrentHashMap<>();
    // 存储用户信息 (userId -> 名称)
    private static final Map<String, String> userNames = new ConcurrentHashMap<>();
    // 存储医生信息 (doctorId -> 名称)
    private static final Map<String, String> doctorNames = new ConcurrentHashMap<>();
    // 存储所有会话 (sessionId -> ConsultationSession)
    private static final Map<String, ConsultationSession> sessions = new ConcurrentHashMap<>();
    // 医生的会话列表 (doctorId -> Set<sessionId>)
    private static final Map<String, Set<String>> doctorSessionMap = new ConcurrentHashMap<>();
    // 用户的会话列表 (userId -> Set<sessionId>)
    private static final Map<String, Set<String>> userSessionMap = new ConcurrentHashMap<>();

    private String currentRole; // "doctor" 或 "user"
    private String currentId;   // 当前连接用户ID

    @OnOpen
    public void onOpen(@PathParam("role") String role, @PathParam("userId") String userId, Session session) {
        System.out.println("新连接: 角色=" + role + ", 用户ID=" + userId); // 添加详细日志

        this.currentRole = role;
        this.currentId = userId;

        if ("doctor".equals(role)) {
            // 医生上线
            doctorSessions.put(userId, session);
            doctorNames.put(userId, userId.replace("consultant_", ""));
            System.out.println("医生上线: " + userId + ", 当前在线医生数: " + doctorSessions.size());

            // 通知所有用户医生列表更新
            broadcastDoctorList();
            sendUserListToDoctor(userId);
        } else {
            // 用户上线
            userSessions.put(userId, session);
            userNames.put(userId, userId);
            System.out.println("用户上线: " + userId + ", 当前在线用户数: " + userSessions.size());

            // 通知所有医生有新用户上线
            broadcastUserList();
            sendDoctorListToUser(userId);
        }
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        try {
            WebSocketMessage wsMessage = new ObjectMapper().readValue(message, WebSocketMessage.class);

            switch (wsMessage.getType()) {
                case WebSocketMessage.TYPE_CHAT:
                    handleChatMessage(wsMessage);
                    break;
                case WebSocketMessage.TYPE_SESSION:
                    handleSessionMessage(wsMessage);
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 处理聊天消息
    private void handleChatMessage(WebSocketMessage message) {
        String sessionId = message.getSessionId();
        ConsultationSession session = sessions.get(sessionId);

        if (session != null && session.isActive()) {
            // 构建转发消息
            WebSocketMessage forwardMsg = new WebSocketMessage();
            forwardMsg.setType(WebSocketMessage.TYPE_CHAT);
            forwardMsg.setSessionId(sessionId);
            forwardMsg.setSenderId(message.getSenderId());
            forwardMsg.setSenderName(message.getSenderName());
            forwardMsg.setContent(message.getContent());
            forwardMsg.setTimestamp(System.currentTimeMillis());

            // 发送给接收方
            String receiverId = "doctor".equals(currentRole) ? session.getUserId() : session.getDoctorId();
            sendMessageToUser(receiverId, forwardMsg);
        }
    }

    // 处理会话相关消息（创建/关闭会话等）
    private void handleSessionMessage(WebSocketMessage message) {
        String action = message.getContent();
        String targetId = message.getReceiverId();

        if ("create".equals(action)) {
            // 创建新会话
            createNewSession(targetId);
        } else if ("close".equals(action)) {
            // 关闭会话
            closeSession(message.getSessionId());
        }
    }
    private void createNewSession(String targetId) {
        // 根据当前角色判断，检查是否已有活跃会话
        String existingSessionId = null;

        if ("doctor".equals(currentRole)) {
            // 医生视角：查找与目标用户的活跃会话
            for (Map.Entry<String, ConsultationSession> entry : sessions.entrySet()) {
                ConsultationSession session = entry.getValue();
                if (session.getDoctorId().equals(currentId) &&
                        session.getUserId().equals(targetId) &&
                        session.isActive()) {
                    existingSessionId = entry.getKey();
                    break;
                }
            }
        } else {
            // 用户视角：查找与目标医生的活跃会话
            for (Map.Entry<String, ConsultationSession> entry : sessions.entrySet()) {
                ConsultationSession session = entry.getValue();
                if (session.getUserId().equals(currentId) &&
                        session.getDoctorId().equals(targetId) &&
                        session.isActive()) {
                    existingSessionId = entry.getKey();
                    break;
                }
            }
        }

        // 如果已有活跃会话，返回现有会话ID，不创建新会话
        if (existingSessionId != null) {
            ConsultationSession existingSession = sessions.get(existingSessionId);
            notifySessionCreated(existingSession); // 通知前端使用现有会话
            return;
        }

        // 以下为原创建会话逻辑（仅在不存在时执行）
        String sessionId = UUID.randomUUID().toString();
        ConsultationSession session = new ConsultationSession();
        // ... 会话初始化代码不变 ...
        if ("doctor".equals(currentRole)) {
            // 医生主动创建会话
            session.setSessionId(sessionId);
            session.setDoctorId(currentId);
            session.setDoctorName(doctorNames.get(currentId));
            session.setUserId(targetId);
            session.setUserName(userNames.get(targetId));
        } else {
            // 用户主动创建会话
            session.setSessionId(sessionId);
            session.setDoctorId(targetId);
            session.setDoctorName(doctorNames.get(targetId));
            session.setUserId(currentId);
            session.setUserName(userNames.get(currentId));
        }
        session.setCreateTime(LocalDateTime.now());
        session.setActive(true);
        sessions.put(sessionId, session);
        // 更新医生会话列表
        doctorSessionMap.computeIfAbsent(session.getDoctorId(), k -> ConcurrentHashMap.newKeySet()).add(sessionId);
        // 更新用户会话列表
        userSessionMap.computeIfAbsent(session.getUserId(), k -> ConcurrentHashMap.newKeySet()).add(sessionId);
        // 通知双方会话已创建
        notifySessionCreated(session);
    }

    // 工具方法：发送消息给指定用户
    private void sendMessageToUser(String userId, WebSocketMessage message) {
        try {
            Session session = doctorSessions.get(userId);
            if (session == null) {
                session = userSessions.get(userId);
            }

            if (session != null && session.isOpen()) {
                synchronized (session) {
                    // 使用配置好的objectMapper序列化
                    String jsonMessage = objectMapper.writeValueAsString(message);
                    session.getBasicRemote().sendText(jsonMessage);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 关闭会话并通知双方
     */
    private void closeSession(String sessionId) {
        ConsultationSession session = sessions.get(sessionId);
        if (session != null) {
            session.setActive(false);

            // 从会话映射中移除
            doctorSessionMap.getOrDefault(session.getDoctorId(), Collections.emptySet()).remove(sessionId);
            userSessionMap.getOrDefault(session.getUserId(), Collections.emptySet()).remove(sessionId);

            // 通知双方会话已关闭
            WebSocketMessage closeMsg = new WebSocketMessage();
            closeMsg.setType("session");
            closeMsg.setSessionId(sessionId);
            closeMsg.setContent("closed");

            // 通知医生
            sendMessageToUser(session.getDoctorId(), closeMsg);
            // 通知用户
            sendMessageToUser(session.getUserId(), closeMsg);

            // 从会话列表中移除
            sessions.remove(sessionId);
        }
    }

    /**
     * 通知会话创建
     */
    private void notifySessionCreated(ConsultationSession session) {
        WebSocketMessage sessionMsg = new WebSocketMessage();
        sessionMsg.setType("session");
        sessionMsg.setSessionId(session.getSessionId());
        sessionMsg.setContent("created");

        // 构建会话信息
        Map<String, Object> sessionInfo = new HashMap<>();
        sessionInfo.put("sessionId", session.getSessionId());
        sessionInfo.put("doctorId", session.getDoctorId());
        sessionInfo.put("doctorName", session.getDoctorName());
        sessionInfo.put("userId", session.getUserId());
        sessionInfo.put("userName", session.getUserName());
        sessionInfo.put("createTime", session.getCreateTime());

        sessionMsg.setData(Collections.singletonList(sessionInfo));

        // 通知医生
        sendMessageToUser(session.getDoctorId(), sessionMsg);
        // 通知用户
        sendMessageToUser(session.getUserId(), sessionMsg);
    }

    /**
     * 广播医生列表更新
     */
    private void broadcastDoctorList() {
        WebSocketMessage msg = new WebSocketMessage();
        msg.setType("doctorList");
        msg.setTimestamp(System.currentTimeMillis());

        List<Map<String, String>> doctorList = new ArrayList<>();
        for (Map.Entry<String, String> entry : doctorNames.entrySet()) {
            Map<String, String> doctor = new HashMap<>();
            doctor.put("id", entry.getKey());
            doctor.put("name", entry.getValue());
            doctorList.add(doctor);
        }

        msg.setData(doctorList);

        // 广播给所有用户
        for (Session session : userSessions.values()) {
            sendMessage(session, msg);
        }
    }

    /**
     * 广播用户列表更新
     */
    private void broadcastUserList() {
        WebSocketMessage msg = new WebSocketMessage();
        msg.setType("userList");
        msg.setTimestamp(System.currentTimeMillis());

        List<Map<String, String>> userList = new ArrayList<>();
        for (Map.Entry<String, String> entry : userNames.entrySet()) {
            Map<String, String> user = new HashMap<>();
            user.put("id", entry.getKey());
            user.put("name", entry.getValue());
            userList.add(user);
        }

        msg.setData(userList);

        // 广播给所有医生
        for (Session session : doctorSessions.values()) {
            sendMessage(session, msg);
        }
    }

    /**
     * 向医生发送用户列表
     */
    private void sendUserListToDoctor(String doctorId) {
        WebSocketMessage msg = new WebSocketMessage();
        msg.setType("userList");
        msg.setTimestamp(System.currentTimeMillis());

        List<Map<String, String>> userList = new ArrayList<>();
        for (Map.Entry<String, String> entry : userNames.entrySet()) {
            Map<String, String> user = new HashMap<>();
            user.put("id", entry.getKey());
            user.put("name", entry.getValue());
            userList.add(user);
        }

        msg.setData(userList);

        // 发送给指定医生
        Session session = doctorSessions.get(doctorId);
        if (session != null) {
            sendMessage(session, msg);
        }
    }

    /**
     * 向用户发送医生列表
     */
    private void sendDoctorListToUser(String userId) {
        WebSocketMessage msg = new WebSocketMessage();
        msg.setType("doctorList");
        msg.setTimestamp(System.currentTimeMillis());

        List<Map<String, String>> doctorList = new ArrayList<>();
        for (Map.Entry<String, String> entry : doctorNames.entrySet()) {
            Map<String, String> doctor = new HashMap<>();
            doctor.put("id", entry.getKey());
            doctor.put("name", entry.getValue());
            doctorList.add(doctor);
        }

        msg.setData(doctorList);

        // 发送给指定用户
        Session session = userSessions.get(userId);
        if (session != null) {
            sendMessage(session, msg);
        }
    }

    /**
     * 向指定会话发送消息
     */
    private void sendMessage(Session session, WebSocketMessage message) {
        try {
            if (session != null && session.isOpen()) {
                synchronized (session) {
                    session.getBasicRemote().sendText(new ObjectMapper().writeValueAsString(message));
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 处理连接关闭
     */
    @OnClose
    public void onClose() {
        if ("doctor".equals(currentRole)) {
            // 医生断开连接
            doctorSessions.remove(currentId);
            doctorNames.remove(currentId);

            // 关闭该医生的所有会话
            Set<String> doctorSessions = doctorSessionMap.getOrDefault(currentId, Collections.emptySet());
            for (String sessionId : doctorSessions) {
                ConsultationSession session = sessions.get(sessionId);
                if (session != null) {
                    // 通知用户医生已离开
                    WebSocketMessage msg = new WebSocketMessage();
                    msg.setType("system");
                    msg.setContent("医生已离开咨询");
                    sendMessageToUser(session.getUserId(), msg);

                    // 关闭会话
                    closeSession(sessionId);
                }
            }

            doctorSessionMap.remove(currentId);
            // 通知所有用户医生列表更新
            broadcastDoctorList();
        } else {
            // 用户断开连接
            userSessions.remove(currentId);
            userNames.remove(currentId);

            // 关闭该用户的所有会话
            Set<String> userSessions = userSessionMap.getOrDefault(currentId, Collections.emptySet());
            for (String sessionId : userSessions) {
                ConsultationSession session = sessions.get(sessionId);
                if (session != null) {
                    // 通知医生用户已离开
                    WebSocketMessage msg = new WebSocketMessage();
                    msg.setType("system");
                    msg.setContent("用户已离开咨询");
                    sendMessageToUser(session.getDoctorId(), msg);

                    // 关闭会话
                    closeSession(sessionId);
                }
            }

            userSessionMap.remove(currentId);
            // 通知所有医生用户列表更新
            broadcastUserList();
        }
    }

    /**
     * 错误处理
     */
    @OnError
    public void onError(Session session, Throwable throwable) {
        System.err.println("WebSocket错误: " + throwable.getMessage());
        throwable.printStackTrace();

        try {
            if (session != null && session.isOpen()) {
                session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, "发生错误"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取用户角色
     */
    private String getUserRole(String userId) {
        if (doctorNames.containsKey(userId)) {
            return "doctor";
        } else if (userNames.containsKey(userId)) {
            return "user";
        }
        return null;
    }

    /**
     * 获取发送者名称
     */
    private String getSenderName() {
        if ("doctor".equals(currentRole)) {
            return doctorNames.get(currentId);
        } else {
            return userNames.get(currentId);
        }
    }
}